#include "miniutil/lenfirstmsgreader.h"

namespace miniutil { namespace multinet {



LenFirstMsgSource_Soc::LenFirstMsgSource_Soc(miniutil::multinet::SocketMulplexService* pse, SOCKET soc)
    :mpss(pse), msoc(soc)
{
}

int LenFirstMsgSource_Soc::Recv(char* pbuf, int len)
{
    return mpss->recv(msoc, pbuf, len);
}


LenFirstMsgSource_Fifo::LenFirstMsgSource_Fifo(miniutil::data::fifobuf *pfifo)
    :mpfifo(pfifo)
{
}

int LenFirstMsgSource_Fifo::Recv(char* pbuf, int len)
{
    return mpfifo->read(pbuf, len);
}




//the format of message must have 4 byte length indicate following message lenth
//-------------------------------------------------------------------------------
LenFirstMsgReader::LenFirstMsgReader()
{
		msglen = -1;
		msghaveread = 0;
		pbuf = NULL;
		memset(tmpbuf, 0x00, sizeof(tmpbuf));
}

LenFirstMsgReader::~LenFirstMsgReader()
{
	Clear();
}

int LenFirstMsgReader::GetMsgBufLen()
{
	return msglen + 4;
}

char* LenFirstMsgReader::RefMsgBuf()
{
	return pbuf;
}	

//the pse(soc) must be readable!
int LenFirstMsgReader::Read(miniutil::multinet::SocketMulplexService* pse, SOCKET soc)
{
    LenFirstMsgSource_Soc source(pse, soc);
    return Read(&source);
}

int LenFirstMsgReader::Read(miniutil::data::fifobuf* pfifo)
{
    LenFirstMsgSource_Fifo source(pfifo);
    return Read(&source);
}

int LenFirstMsgReader::Read(LenFirstMsgSource* psrc)
{
	int ret = 0, ret2;
	int lentoread = 0;
	if(msglen == -1)
	{
		lentoread = 4-msghaveread;
        ret = psrc->Recv(tmpbuf+msghaveread, lentoread);
		if(ret == -1 || ret == 0)
			return -1;
		msghaveread += ret;
		if(msghaveread == 4)
		{
			msglen = ntohl(*(int*)(tmpbuf));
			pbuf = new char[msglen+4];
			memcpy(pbuf, tmpbuf, 4);
			
			msghaveread = 0;
		}
	}
	
	if(msglen != -1)
	{
		lentoread = msglen - msghaveread;
		ret2 = psrc->Recv(pbuf+4+msghaveread, lentoread);
		if(ret2 == -1 || (ret2 ==0 && ret == 0))
			return -1;
		msghaveread += ret2;
	}
	
	if(msglen != -1 && msglen == msghaveread)
		return 1;
		
	return 0;
}

int LenFirstMsgReader::Clear()
{
	msglen = -1;
	msghaveread = 0;
	if(!pbuf)
		delete []pbuf;
	pbuf = NULL;
	memset(tmpbuf, 0x00, sizeof(tmpbuf));
	return 0;
}
	
} }

	